package mobilefeel.sdk;

import java.io.Serializable;
import java.util.UUID;

import mobilefeel.dto.TouchEvent;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.util.Log;

public final class MobileFeelService extends Service {

	private NetworkController network;
	private SensorController sensor;
	private TouchScreenController touchscreen;
	
    public static final String ON_RESUME = "mobilefeel.sdk.ON_RESUME";
    public static final String ON_PAUSE = "mobilefeel.sdk.ON_PAUSE";
    public static final String CONNECT = "mobilefeel.sdk.CONNECT";
    public static final String DISCONNECT = "mobilefeel.sdk.DISCONNECT";
    public static final String REGISTER_VIEW = "mobilefeel.sdk.REGISTER_VIEW";
    public static final String CLICK_EVENT = "mobilefeel.sdk.CLICK_EVENT";
    public static final String LONGCLICK_EVENT = "mobilefeel.sdk.LONGCLICK_EVENT";
    public static final String TOUCH_EVENT = "mobilefeel.sdk.TOUCH_EVENT";
    public static final String CUSTOM_DATA = "mobilefeel.sdk.CUSTOM_DATA";
    
    public static final String IP = "mobilefeel.sdk.IP";
    public static final String PORT = "mobilefeel.sdk.PORT";
    public static final String TIMEOUT = "mobilefeel.sdk.TIMEOUT";
    public static final String ID = "mobilefeel.sdk.ID";
    public static final String NAME = "mobilefeel.sdk.NAME";
	public static final String WIDTH = "mobilefeel.sdk.WIDTH";
	public static final String HEIGHT = "mobilefeel.sdk.HEIGHT";
    public static final String MOTION_EVENT = "mobilefeel.sdk.MOTION_EVENT";
    public static final String TEXT = "mobilefeel.sdk.TEXT";
    public static final String OBJECT = "mobilefeel.sdk.OBJECT";
    
    private String deviceId;
    private SharedPreferences preferences;
    public static final String PREFERENCES = "mobilefeel.sdk";
    
	@Override
	public void onCreate(){
		super.onCreate();
        
		preferences = getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE);
		deviceId = preferences.getString("deviceId", "null");
		if(deviceId.equals("null"))
			deviceId = generateRandomId();
		
        network = new NetworkController(this);
        sensor = new SensorController(this, network);
        touchscreen = new TouchScreenController(this, network);
	}
	
	void onResume(){
        sensor.onResume();
	}
	
	void onPause(){
        sensor.onPause();
	}
	
	@Override
	public void onDestroy(){
        super.onDestroy();
        
        sensor.unregisterAccelerometerEvent();
        network.disconnect();
        
        Log.d("MobileFeel", "Service stopped");
	}
	
	@Override 
	public int onStartCommand(Intent intent, int flags, int startId) {
		if(intent.getAction() != null){
			if (intent.getAction().equals(ON_RESUME)){
				this.onResume();
			} else if(intent.getAction().equals(ON_PAUSE)){
				this.onPause();
			} else if(intent.getAction().equals(CONNECT)){
				this.network.connect(intent.getStringExtra(IP), intent.getIntExtra(PORT,51560), intent.getIntExtra(TIMEOUT, 10000));
			} else if(intent.getAction().equals(DISCONNECT)){
				this.network.disconnect();
			} else if(intent.getAction().equals(REGISTER_VIEW)) {
				this.touchscreen.registerView(intent.getIntExtra(ID, 0xffffffff), intent.getStringExtra(NAME), intent.getIntExtra(WIDTH, 0), intent.getIntExtra(HEIGHT, 0));
			} else if(intent.getAction().equals(CLICK_EVENT)) {
				this.touchscreen.onClick(intent.getIntExtra(ID, 0));
			} else if(intent.getAction().equals(LONGCLICK_EVENT)) {
				this.touchscreen.onLongClick(intent.getIntExtra(ID, 0));
			} else if(intent.getAction().equals(TOUCH_EVENT)) {
				this.touchscreen.onTouch(intent.getIntExtra(ID, 0xffffffff), (TouchEvent)intent.getSerializableExtra(MOTION_EVENT));
			} else if(intent.getAction().equals(CUSTOM_DATA)) {
				this.network.sendCustomData(intent.getStringExtra(TEXT), intent.getSerializableExtra(OBJECT));
			}
		}
		return START_STICKY;
	}		
	
	void registerAccelerometerEvent() {
		this.sensor.registerAccelerometerEvent();
	}

	void unregisterAccelerometerEvent() {
		this.sensor.unregisterAccelerometerEvent();
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	void disconnect() {
		this.unregisterAccelerometerEvent();
		
		Intent intent = new Intent(MobileFeelActivity.UNREGISTER_ALL_EVENTS);
		sendBroadcast(intent);
	}
    
	private String generateRandomId(){
		String id = Long.toHexString(UUID.randomUUID().getMostSignificantBits());
		SharedPreferences.Editor editor = preferences.edit();
		editor.putString("deviceId", id);
		editor.commit();
		return id;
	}

	String getDeviceId() {
		return deviceId;
	}

	void setAccelerometerRate(int rate) {
		sensor.setAccelerometerRate(rate);
	}

	void connectionEstablished() {
		Intent intent = new Intent(MobileFeelActivity.CONNECTION_ESTABLISHED);
		sendBroadcast(intent);
	}

	void registerOnClickEvent(int id) {
		Intent intent = new Intent(MobileFeelActivity.REGISTER_CLICK_EVENT);
		intent.putExtra(MobileFeelActivity.VIEW_ID, id);
		sendBroadcast(intent);
	}

	void unregisterOnClickEvent(int id) {
		Intent intent = new Intent(MobileFeelActivity.UNREGISTER_CLICK_EVENT);
		intent.putExtra(MobileFeelActivity.VIEW_ID, id);
		sendBroadcast(intent);
	}

	void registerOnLongClickEvent(int id) {
		Intent intent = new Intent(MobileFeelActivity.REGISTER_LONGCLICK_EVENT);
		intent.putExtra(MobileFeelActivity.VIEW_ID, id);
		sendBroadcast(intent);
	}

	void unregisterOnLongClickEvent(int id) {
		Intent intent = new Intent(MobileFeelActivity.UNREGISTER_LONGCLICK_EVENT);
		intent.putExtra(MobileFeelActivity.VIEW_ID, id);
		sendBroadcast(intent);
	}
	
	void registerOnTouchEvent(int id) {
		Intent intent = new Intent(MobileFeelActivity.REGISTER_TOUCH_EVENT);
		intent.putExtra(MobileFeelActivity.VIEW_ID, id);
		sendBroadcast(intent);
	}

	void unregisterOnTouchEvent(int id) {
		Intent intent = new Intent(MobileFeelActivity.UNREGISTER_TOUCH_EVENT);
		intent.putExtra(MobileFeelActivity.VIEW_ID, id);
		sendBroadcast(intent);
	}

	void connectionFailed(String message) {
		Intent intent = new Intent(MobileFeelActivity.CONNECTION_FAILED);
		intent.putExtra(MobileFeelActivity.CONNECTION_FAILED_REASON, message);
		sendBroadcast(intent);
	}

	void receiveCustomData(String text, Serializable object) {
		Intent intent = new Intent(MobileFeelActivity.CUSTOM_DATA);
		intent.putExtra(MobileFeelActivity.TEXT, text);
		intent.putExtra(MobileFeelActivity.OBJECT, object);
		sendBroadcast(intent);
	}

	void receiveDisconnect() {
		Intent intent = new Intent(MobileFeelActivity.DISCONNECTION);
		sendBroadcast(intent);
	}

}